#pragma once

#include "Buffer.h"

#include "Callbacks.h"
#include "Channel.h"
#include "EventLoop.hpp"
#include "Logger.h"
#include "Socket.h"

// connection tcpserver...

/**
 * 思路：一个连接通道：对连接进行全方位的管理，对通信连接的所有操作都是通过这个模块提供的功能完成的
 * TcpServer -》 Acceptor -》 有一个新用户连接，拿到 fd -》 Connection设置回调 -》 Channel -》 Poller -》Channel回调操作
 * 处理读：
 * 处理写：
 *
 */

/*
important functions:
1. HandleRead
2. HandleWrite
*/

namespace devem {

typedef enum { DISCONNECTED, CONNECTED, CONNECTING, DISCONNECTING } ConnStatu;

class Connection : public std::enable_shared_from_this<Connection> {
public:
    void SetStatu(ConnStatu statu) { statu_ = statu; }

    Connection(int sockfd, EventLoop* loop)
        : sockfd_(sockfd), socket_(sockfd_), loop_(loop), channel_(new Channel(sockfd_, loop)) {
        channel_->SetReadCallBack(std::bind(&Connection::HandleRead, this));
        channel_->SetWriteCallBack(std::bind(&Connection::HandleWrite, this));
        channel_->SetErrorCallBack(std::bind(&Connection::HandleError, this));
    }

    /*
        输入缓冲区：读区域 = 待业务处理的数据，写区域 = 新接收的数据
        输出缓冲区：读区域 = 待网络发送的数据，写区域 = 用户新提交的数据
    */

    void HandleRead() {
        char buf[1024];
        ssize_t ret = socket_.Recv(buf, sizeof(buf) - 1, MSG_DONTWAIT);
        if (ret <= 0) {
            // 出错了
            return HandleError();
        }
        // 成功了
        in_buffer_.Write(buf, ret);
        // 已建立的连接可读，调用传入的回调函数
        if (in_buffer_.Readable()) {
            message_callback_(shared_from_this(), &in_buffer_);
        }
    }

    void HandleWrite() {
        ssize_t ret = socket_.Send(out_buffer_.ReadIndex(), out_buffer_.Readable(), MSG_DONTWAIT);
        if (ret < 0) {
            if (in_buffer_.Readable()) {
                message_callback_(shared_from_this(), &in_buffer_);
            }
            // 出错了
            return HandleClose();
        }
        out_buffer_.MoveReadOffset(ret);
        if (out_buffer_.Readable() == 0) {
            // 没有数据要发送了,关闭写事件监视
            channel_->DisableWrite();
        }
    }

    void HandleClose() {
        if (in_buffer_.Readable()) {
            message_callback_(shared_from_this(), &in_buffer_);
        }
        // SetStatu(DISCONNECTED);
        // release
    }

    void HandleError() { HandleClose(); }

    // 连接管理

    void EstablishInLoop() { channel_->EnableRead(); }

    void ReleaseInLoop() {
        loop_->RemoveEvent(channel_);
        socket_.Close();
    }

public:
    int Fd() { return sockfd_; }

    void SetConnectionCallback(const ConnectedCallback cb) { connection_callback_ = cb; }

    void SetMessageCallback(const MessageCallback cb) { message_callback_ = cb; }

private:
    uint64_t conn_id_;  // 唯一的ID，便于管理
    int sockfd_;
    Socket socket_;
    Channel* channel_;
    EventLoop* loop_;  // subloop
    ConnStatu statu_;
    Buffer in_buffer_;
    Buffer out_buffer_;

    ConnectedCallback connection_callback_;  // 有新连接时的回调
    MessageCallback message_callback_;       // 有读写消息时的回调
};
}  // namespace devem